//
// Created by taojiaheng on 2020/5/29.
//
#include "Timer.h"

Timer * Timer::timer = new Timer();
Timer::Timer() {
    _init();
}

Timer::~Timer() {
}

/**
 * 初始化定时器
 */
void Timer::_init() {
    epoll_fd = epoll_create(TIMER_MAX_COUNT);
    if(epoll_fd < 0) {
        printf("初始化定时器 管理 Epoll 失败\n");
        exit(-1);
    }
}

/**
 * 运行定时器
 */
void * Timer::_run(void * _timer) {
    Timer * timer = (Timer*) _timer;
    epoll_event events[EPOLL_EVENTS];
    while (true) {
        int num = epoll_wait(timer->epoll_fd, events, EPOLL_EVENTS, -1);
        for(int i = 0; i < num; i++) {
            if(events[i].events & EPOLLIN) {
                TimerTask *task = (TimerTask *) events[i].data.ptr;
                timer->disposeTimerTask(task);
            }
        }
    }
}

/**
 * 在新线程中运行定时器
 */
void Timer::run() {
    pthread_t thread_id;
    int ret = pthread_create(&thread_id, NULL, Timer::_run, this);
    if(ret != 0) {
        printf("定时器线程创建失败\n");
    }
}

/**
 * 处理定时器
 */
void Timer::disposeTimerTask(TimerTask * task) {
    // 先读取数据 防止重复触发
    char * buff = new char[MAX_SIZE];
    read(task->fd, buff, MAX_SIZE);
    delete []buff;
    // 检查定时器剩余执行次数 必须是循环定时器情况下进行检查
    if(task->getTimerType() == 2 && task->timer_exec_count != -1) {
        if(task->timer_exec_count == 0){
            deleteTimerTask(task);
            return;
        }else{
            task->timer_exec_count--;
        }
    }
    // 执行自定义函数
    task->callBack();
    // 检查是否重复触发 如果不是重复触发 停止定时器
    if(task->getTimerType() == 1) {
        deleteTimerTask(task);
    }
    // 检查定时器是否执行完毕
    if(task->getTimerType() == 2 && task->timer_exec_count == 0) {
        deleteTimerTask(task);
    }
}


void Timer::deleteTimerTask(TimerTask * task) {
    epoll_event event;
    event.events = EPOLLOUT;
    event.data.fd = task->fd;
    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, task->fd, &event);
    // 执行回调
    task->callDestroyCallBack();
    // 释放内存
    delete task;
}


/**
 * 添加定时器
 */
bool Timer::addTimer(TimerTask * timerTask) {
    // 检查必须的参数是否设置
    if(!timerTask->checkParameter()){
        printf("timer task 参数设置错误\n");
        return false;
    }
    int timer_task_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK);
    if(timer_task_fd < 0) {
        printf("timer_task_fd 错误\n");
        return false;
    }
    // 设置第一次超时时间 和 第一次之后每一次的超时时间
    struct timespec startTime, intervalTime;
    startTime.tv_nsec = timerTask->getNanosecond() % 1000000000;
    startTime.tv_sec = timerTask->getNanosecond() / 1000000000;
    intervalTime.tv_nsec = timerTask->getNanosecond() % 1000000000;
    intervalTime.tv_sec = timerTask->getNanosecond() / 1000000000;
    struct itimerspec newValue;
    newValue.it_value = startTime;
    newValue.it_interval = intervalTime;
    // 设置超时 且为相对时间
    if(timerfd_settime(timer_task_fd, 0, &newValue, NULL) < 0) {
        printf("timerfd_settime 错误\n");
        return false;
    }
    timerTask->fd = timer_task_fd;
    epoll_event event;
    event.data.ptr = timerTask;
    event.events = EPOLLIN;
    if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, timer_task_fd, &event) == -1){
        printf("epoll_ctl Add fd:%d error, Error:[%d:%s]\n", timer_task_fd, errno, strerror(errno));
        return false;
    }
    return true;
}



TimerTask::TimerTask() {
    printf("该类不能被自动初始化\n");
    exit(-100);
}

TimerTask::~TimerTask() {

}

/**
 * 设置调用的函数指针
 * @param _call_func_ptr 调用的函数指针
 */
void TimerTask::setCallFuncPtr(void(*_call_func_ptr)(void *)) {
    call_func_ptr = _call_func_ptr;
}

/**
 * 定时器任务类构造函数
 * @param _nanosecond 定时器间隔 纳秒
 * @param _timer_type 定时器类型 1 单次定时器 2 循环定时器
 * @param _is_new_thread 是否在新的线程中运行定时器
 */
TimerTask::TimerTask(unsigned long long _nanosecond, char _timer_type, bool _is_new_thread) {
    // 参数初始化默认值
    if(_timer_type == 0) _timer_type = 1; // 定时器类型
    nanosecond = _nanosecond; // 运行时间
    timer_type = _timer_type; // 定时器类型
    is_new_thread = _is_new_thread; // 是否新线程运行
    timer_exec_count = -1; // 执行次数
    call_func_destroy_ptr = NULL; // 执行完毕回调
    call_func_ptr = NULL; // 执行回调
    _ptr = NULL; // 附带数据
}

/**
 * 获取定时器间隔
 * @return 时间间隔 单位纳秒
 */
unsigned long long TimerTask::getNanosecond() {
    return nanosecond;
}

/**
 * 获取定时器类型
 * @return
 */
char TimerTask::getTimerType() {
    return timer_type;
}

/**
 * 执行回调函数
 */
void TimerTask::callBack() {
    call_func_ptr(_ptr);
}

void TimerTask::setCallFuncDestroyPtr(void (*_call_func_destroy_ptr)(void *)) {
    call_func_destroy_ptr = _call_func_destroy_ptr;
}

bool TimerTask::checkParameter() {
    if(call_func_ptr == NULL || call_func_destroy_ptr == NULL) return false;
    return true;
}

void TimerTask::callDestroyCallBack() {
    call_func_destroy_ptr(_ptr);
}
